﻿<!DOCTYPE html>
<html>
<head>
<!--

  Copyright (c) 2015-2018 Jean-Marc VIGLINO, 
  released under CeCILL-B (french BSD like) licence: http://www.cecill.info/
  
-->
  <title>ol-ext: Undo/redo</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  <meta name="description" content="ol.interaction.UndoRedo is an interaction to handle undo on a map." />
  <meta name="keywords" content="ol, openlayers, undo, interaction" />

  <link rel="stylesheet" href="../style.css" />

  <!-- jQuery -->
  <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
  <!-- FontAwesome -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
  
  <!-- Openlayers -->
  <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" />
  <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
  <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script>
  
  <!-- ol-ext -->
  <link rel="stylesheet" href="../../dist/ol-ext.css" />
  <script type="text/javascript" src="../../dist/ol-ext.js"></script>

  <style>
    .ol-button i {
      color: inherit;
    }
    .ol-button.red button,
    .ol-button.green button,
    .ol-button.blue button {
      color: #f00;
      background-color: currentColor;
      border: 2px solid currentColor;
      width: 1em;
      height: 1em;
      border-radius: 0;
    }
    .ol-button.green button {
      color: #0f0;
    }
    .ol-button.blue button {
      color: #00f;
    }
    .ol-button.red button:hover,
    .ol-button.green button:hover,
    .ol-button.blue button:hover {
      background-color: currentColor!important;
      border-color: #000;
    }
  </style>

</head>
<body >
  <a href="https://github.com/Viglino/ol-ext" class="icss-github-corner"><i></i></a>

  <a href="../../index.html">
    <h1>ol-ext: Undo/redo</h1>
  </a>
  <div class="info">
    <p>
      <i>ol/interaction/UndoRedo</i> is an interaction to handle undo/redo on a map.
    </p>
    <p>
      <span class="experimental">Experimental</span>
      this feature is still in progress and may be buggy.
    </p>
    <p>
      Just add the interaction to the map to get it working.
      It will watch all vector sources and all interactions in the map.
      Use the <i>undo</i> and <i>redo</i> method to undo the last recorded operations.
      <br/>
      Undo can be stacked in a block to make them undoing at a time. 
      Just enclose the operation between a <i>blockStart()</i> and <i>blockEnd()</i>.
      <br/>
      You can stack operation on a map by enclosing operations beetween 
      <i>undoblockstart</i> and <i>undoblockend</i> events
      (<i>map.dispatchEvent('undoblockstart')</i> and <i>map.dispatchEvent('undoblockend')</i>).
    </p>
    Cancelable operations:
    <ul>
      <li>
        <b>ol/source/Vector</b> 
        <i>addFeature</i> / <i>removeFeature</i> / <i>clear</i>
        <br/>
        The core <i>clear</i> function has been overwritten to fires 
        a <i>clearstart</i> and <i>clearend</i> event
      </li>
    </ul>
    <br/>
    Cancelable interactions:
    <ul>
      <li>
        <b>ol/interaction/Draw</b> (ol core interaction)
      </li>
      <li>
        <a href="../interaction/map.interaction.modifyfeature.html">
          <b>ol/interaction/ModifyFeature</b> 
        </a>
        The core <i>ol/interaction/Modify</i> has been rewritten to handle modification 
        start / end events
        (see <a href="../interaction/map.interaction.modifyfeature.html">example</a>)
      </li>
      <li>
        <b>ol/interaction/Delete</b>
      </li>
      <li>
        <a href="../interaction/map.interaction.drawhole.html">
          <b>ol/interaction/DrawHole</b>
        </a>
      </li>
      <li>
        <a href="../interaction/map.interaction.transform.html">
          <b>ol/interaction/Transform</b>
        </a>
      </li>
      <li>
        <a href="../interaction/map.interaction.split.html">
          <b>ol/interaction/Split</b>
        </a>
      </li>
      <li>
        <a href="../interaction/map.interaction.offset.html">
          <b>ol/interaction/Offset</b>
        </a>
      </li>
      <li>
        <b>ol/interaction/FillAttribute</b>
      </li>
    </ul>
  </div>

  <!-- Map div -->
  <div id="map" style="width:600px; height:400px;"></div>

  <div class="options" >
    <div id="info"></div>
  </div>

  <script type="text/javascript">

    //  Vector layer
    var vector = new ol.layer.Vector( { 
      source: new ol.source.Vector(),
      style: function (f) {
        return new ol.style.Style({
          image: new ol.style.Circle({
            radius: 5,
            stroke: new ol.style.Stroke({ width: 1.5, color: f.get('color') || [255,128,0] }),
            fill: new ol.style.Fill({ color: (f.get('color') || [255,128,0]).concat([.3]) })
          }),
          stroke: new ol.style.Stroke({ width: 2.5, color: f.get('color') || [255,128,0] }),
          fill: new ol.style.Fill({ color: (f.get('color') || [255,128,0]).concat([.3]) })
        })
      }
    })

    // The map
    var map = new ol.Map ({
        target: 'map',
        view: new ol.View ({
          zoom: 14,
          center: [270701, 6247637]
        }),
        layers: [
          new ol.layer.Tile({ source: new ol.source.OSM() }),
          vector
        ]
      });


    // Main control bar
    var mainbar = new ol.control.Bar();
    map.addControl(mainbar);

    // Editbar
    var editbar = new ol.control.EditBar ({
      source: vector.getSource(),
      interactions: { Info: false }
    });
    mainbar.addControl(editbar);

    // Add a fill interaction toset color attribute
    var fill = new ol.interaction.FillAttribute({}, { color: [255,0,0] });
    editbar.addControl(new ol.control.Toggle({
      html: '<i class="fa fa-paint-brush"></i>',
      title: 'fill color attribut',
      interaction: fill,
      bar: new ol.control.Bar({
        controls:[ 
          new ol.control.Button({
            className: 'red',
            handleClick: function(){
              fill.setAttribute('color', [255,0,0])
            }
          }),
          new ol.control.Button({
            className: 'green',
            handleClick: function(){
              fill.setAttribute('color', [0,255,0])
            }
          }),
          new ol.control.Button({
            className: 'blue',
            handleClick: function(){
              fill.setAttribute('color', [0,0,255])
            }
          })
        ]
      })
    }));

    // Undo redo interaction
    var undoInteraction = new ol.interaction.UndoRedo();
    map.addInteraction(undoInteraction);
    // Prevent selection of a deleted feature
    undoInteraction.on('undo', function(e) {
      if (e.action.type === 'addfeature') {
        editbar.getInteraction('Select').getFeatures().clear();
        editbar.getInteraction('Transform').select();
      }
    });

    // Add buttons to the bar
    var bar = new ol.control.Bar({ 
      group: true,
      controls: [
        new ol.control.Button({
          html: '<i class="fa fa-undo" ></i>',
          title: 'undo...',
          handleClick: function() {
            undoInteraction.undo();
          }
        }),
        new ol.control.Button({
          html: '<i class="fa fa-repeat" ></i>',
          title: 'redo...',
          handleClick: function() {
            undoInteraction.redo();
          }
        })
      ]
    });
    mainbar.addControl(bar);

    // Add a snap
    map.addInteraction(new ol.interaction.Snap({ 
      source: vector.getSource() 
    }));

  </script>

</body>
</html>